//==============================================================================
#include "Entity.h"
#include "SoundBank.h"
//==============================================================================
std::vector<CEntity*> 	CEntity::PlayerList;
std::vector<CEntity*> 	CEntity::ProjectileList;
int CEntity::mouseX;
int CEntity::mouseY;
//==============================================================================
CEntity::CEntity() {
	Surf_Entity = new SDL_Surface;
	Surf_FrozenPlayer = new SDL_Surface;

	X = 0;
	Y = 0;

	playerScore = 0;
	playerDeaths = 0;
	
	Width 	= 0;
	Height 	= 0;
	name = "";
	char* Name = NULL;
	MoveLeft  = false;
	MoveRight = false;
	CanJump = false;
	damage = 0;
	oldTime = 0;
	newTime = 0;
	frozen = true;
	freezeTime = 0;

	Type = 	ENTITY_TYPE_GENERIC;

	Flags = ENTITY_FLAG_GRAVITY;

	SpeedX = 0;
	SpeedY = 0;
	speedX = 0.5;

	AccelX = 0;
	AccelY = 0;

	MaxSpeedX = 10;
	MaxSpeedY = 12;

	CurrentFrameCol = 0;
	CurrentFrameRow = 0;

	Col_X = 0;
	Col_Y = 0;

	Col_Width  = 0;
	Col_Height = 0;
}

//------------------------------------------------------------------------------
CEntity::~CEntity() {
}

void CEntity::flash()
{
	for(int i = 100; i > 0; i-=10)
	{
		if(PosValid(X+i, Y))
		{
			X += i;
			break;
		}
	}
	
}


bool CEntity::Jump()
{
	if(!CanJump)
		return false;

	SpeedY = -MaxSpeedY;

	CanJump = false;
	return true;
}

//==============================================================================
bool CEntity::OnLoad(char* File, int Width, int Height, int MaxFrames) {
	if((Surf_Entity = CSurface::OnLoad(File)) == NULL) {
		return false;
	}

	CSurface::Transparent(Surf_Entity, 255, 0, 255);

	this->Width = Width;
	this->Height = Height;

	Anim_Control.MaxFrames = MaxFrames;

    return true;
}

//------------------------------------------------------------------------------
void CEntity::OnLoop() {
	//We're not Moving
	if(MoveLeft == false && MoveRight == false) {
		StopMove();
	}

	if(MoveLeft && SpeedX>0)
		SpeedX=0;
	else if(MoveRight && SpeedX<0)
		SpeedX=0;

	if(MoveLeft) {
		AccelX = -speedX;
	}else if(MoveRight) {
		AccelX = speedX;
	}else
	{
		SpeedX = AccelX = 0;
	}
	if(Flags & ENTITY_FLAG_GRAVITY && !CanJump)
	{
		AccelY = 0.75f;
	}

	SpeedX += AccelX * CFPS::FPSControl.GetSpeedFactor();
	SpeedY += AccelY * CFPS::FPSControl.GetSpeedFactor();

	if(SpeedX > MaxSpeedX)  SpeedX =  MaxSpeedX;
	if(SpeedX < -MaxSpeedX) SpeedX = -MaxSpeedX;
	if(SpeedY > MaxSpeedY)  SpeedY =  MaxSpeedY;
	if(SpeedY < -MaxSpeedY) SpeedY = -MaxSpeedY;

	if(!frozen)
	{
		OnAnimate();
		OnMove(SpeedX, SpeedY);
	}
}

//------------------------------------------------------------------------------
void CEntity::OnRender(SDL_Surface* Surf_Display,int playerID) {
    if(Surf_Entity == NULL || Surf_Display == NULL) return;

    CSurface::OnDraw(Surf_Display, Surf_Entity, X - CCamera::CameraControl.GetX(), Y - CCamera::CameraControl.GetY(), CurrentFrameCol * Width, (CurrentFrameRow + Anim_Control.GetCurrentFrame()) * Height, Width, Height,playerID);
}

//------------------------------------------------------------------------------
void CEntity::OnCleanup() {
    if(Surf_Entity != NULL) {
        SDL_FreeSurface(Surf_Entity);
    }

    Surf_Entity = NULL;
}

//------------------------------------------------------------------------------
void CEntity::OnAnimate() {
	if(MoveLeft) {
		CurrentFrameCol = 0;
	}else

	if(MoveRight) {
		CurrentFrameCol = 1;
	}

	Anim_Control.OnAnimate();
}

//------------------------------------------------------------------------------
bool CEntity::OnCollision(CEntity* Entity) {
	return true;
}

void CEntity::RunCollision(CEntity* Entity)
{
	return;
}

void CEntity::CastProjectile(int identify)
{
	return;
}

bool CEntity::OnProjectileMove(int newX, int newY)
{
	if(PosValid(newX, newY))
		return false;
	else
		return true;
}

//==============================================================================
void CEntity::OnMove(float MoveX, float MoveY) {
		if(MoveX < 0 )
		{	facingRight = false;
			facingLeft = true;
		}
		else if(MoveX > 0 )
		{	facingLeft = false;
			facingRight = true;
		}

		if(MoveX == 0 && MoveY == 0) return;

		double NewX = 0;
		double NewY = 0;

		MoveX *= CFPS::FPSControl.GetSpeedFactor();
		MoveY *= CFPS::FPSControl.GetSpeedFactor();

		if(MoveX != 0) {

			if(MoveX >= 0) 	NewX =  CFPS::FPSControl.GetSpeedFactor();
			else 			NewX = -CFPS::FPSControl.GetSpeedFactor();
		}

		if(MoveY != 0) {
			if(MoveY >= 0) 	NewY =  CFPS::FPSControl.GetSpeedFactor();
			else 			NewY = -CFPS::FPSControl.GetSpeedFactor();
		}

		while(true) {
			if(Flags & ENTITY_FLAG_GHOST) {
				PosValid((int)(X + NewX), (int)(Y + NewY)); //We don't care about collisions, but we need to send events to other entities

				X += NewX;
				Y += NewY;
			}else{
				if(PosValid((int)(X + NewX), (int)(Y))) {
					X += NewX;
				}else{
					SpeedX = 0;
				}

				if(PosValid((int)(X), (int)(Y + NewY))) {
					Y += NewY;
				}else{
					SpeedY = 0;
				}
			}
			if(!PosValid((int)(X), (int)(Y + 1)))
			{
				CanJump = true;
			}
			MoveX += -NewX;
			MoveY += -NewY;

			if(NewX > 0 && MoveX <= 0) NewX = 0;
			if(NewX < 0 && MoveX >= 0) NewX = 0;

			if(NewY > 0 && MoveY <= 0) NewY = 0;
			if(NewY < 0 && MoveY >= 0) NewY = 0;

			if(MoveX == 0) NewX = 0;
			if(MoveY == 0) NewY = 0;

			if(MoveX == 0 && MoveY 	== 0) 	break;
			if(NewX  == 0 && NewY 	== 0) 	break;
		
			casting = false;
		}
}

//------------------------------------------------------------------------------
void CEntity::StopMove() {
	if(SpeedX > 0) {
		AccelX = -1;
	}

	if(SpeedX < 0) {
		AccelX =  1;
	}

	if(SpeedX < 2.0f && SpeedX > -2.0f) {
		AccelX = 0;
		SpeedX = 0;
	}
}

//==============================================================================
bool CEntity::Collides(int oX, int oY, int oW, int oH) {
    int left1, left2;
    int right1, right2;
    int top1, top2;
    int bottom1, bottom2;

	int tX = (int)X + Col_X;
	int tY = (int)Y + Col_Y;

    left1 = tX;
    left2 = oX;

    right1 = left1 + Width - 2 - Col_Width;
    right2 = oX + oW - 1;

    top1 = tY;
    top2 = oY;

    bottom1 = top1 + Height - 2 - Col_Height;
    bottom2 = oY + oH - 1;


    if (bottom1 < top2) 
	{
		return false;
	}
    if (top1 > bottom2) 
	{
		return false;
	}
    if (right1 < left2) 
	{
		return false;
	}
    if (left1 > right2)
	{
		return false;
	}

    return true;
}

//==============================================================================
bool CEntity::PosValid(int NewX, int NewY) {
	bool Return = true;

	int StartX 	= (NewX + Col_X) / TILE_SIZE;
	int StartY 	= (NewY + Col_Y) / TILE_SIZE;

	int EndX	= ((NewX + Col_X) + Width - Col_Width - 2) 		/ TILE_SIZE;
	int EndY	= ((NewY + Col_Y) + Height - Col_Height - 2)	/ TILE_SIZE;

	if(EndX < 1 || EndY < 1 || EndX > (MAP_WIDTH*3) || EndY > MAP_HEIGHT*3)
		return false;

	if(NewX > (((TILE_SIZE*MAP_WIDTH)*3)-32)) // 32 specific for the character size. Should be changed to dynamic.
		return false;

	for(int iY = StartY;iY <= EndY;iY++) {
		for(int iX = StartX;iX <= EndX;iX++) {
			CTile* Tile = CArea::AreaControl.GetTile(iX * TILE_SIZE, iY * TILE_SIZE);

			if(PosValidTile(Tile) == false) {
				Return = false;
			}
		}
	}

	if(Flags & ENTITY_FLAG_MAPONLY) {
	}else{
		for(int i = 0;i < PlayerList.size();i++) {
			//Both entity and player?
			if(PosValidEntity(PlayerList[i], NewX, NewY) == false && !(PlayerList[i]->Type == ENTITY_TYPE_PLAYER && Type & ENTITY_TYPE_PLAYERSPELL) && !(PlayerList[i]->Type == ENTITY_TYPE_PLAYERSPELL && Type & ENTITY_TYPE_PLAYER)) {
				Return = false;
			}
		}

		for(int i = 0;i < ProjectileList.size();i++) {
			//Both entity and player?
			if(PosValidEntity(ProjectileList[i], NewX, NewY) == false && !(ProjectileList[i]->Type == ENTITY_TYPE_PLAYER && Type & ENTITY_TYPE_PLAYERSPELL) && !(ProjectileList[i]->Type == ENTITY_TYPE_PLAYERSPELL && Type & ENTITY_TYPE_PLAYER)) {
				Return = false;
			}
		}
	}

	return Return;
}

//------------------------------------------------------------------------------
bool CEntity::PosValidTile(CTile* Tile) {
	if(Tile == NULL) {
		return true;
	}

	if(Tile->TypeID == TILE_TYPE_BLOCK) {
		return false;
	}

	return true;
}

//------------------------------------------------------------------------------
bool CEntity::PosValidEntity(CEntity* Entity, int NewX, int NewY) {
	if(this != Entity && Entity != NULL &&
		Entity->Flags ^ ENTITY_FLAG_MAPONLY &&
		Entity->Collides(NewX + Col_X, NewY + Col_Y, Width - Col_Width - 1, Height - Col_Height - 1) == true) {

		CEntityCol EntityCol;

		EntityCol.EntityA = this;
		EntityCol.EntityB = Entity;

		CEntityCol::EntityColList.push_back(EntityCol);
		if(this->Type == ENTITY_TYPE_PLAYERSPELL || Entity->Type == ENTITY_TYPE_PLAYERSPELL) // Neither of the entities are playerspells, don't want the NPC's to jump when "standing" on top of a spell.
		{
			return true;
		}
		return false;
	}

	return true;
}

//==============================================================================
